﻿using System;
using System.ServiceModel.Syndication;
using System.Windows;
using Jacobi.Seesmic.FeedReader.Model;
using Seesmic.Sdp.Utils;

namespace Jacobi.Seesmic.FeedReader.PluginSettingsView
{
    /// <summary>
    /// The view model for the view that edits the feed information.
    /// </summary>
    public sealed class EditFeedInfoViewModel : ObservableObject
    {
        /// <summary>
        /// Constructs a new instance based on the specified <paramref name="feedInfos"/>.
        /// </summary>
        /// <param name="feedInfos">Must not be null.</param>
        internal EditFeedInfoViewModel(FeedInfoCollection feedInfos)
        {
            FeedInfos = feedInfos;
        }

        private EditFeedInfoView _view;

        /// <summary>
        /// A wrapper method to show the view.
        /// </summary>
        /// <remarks>
        /// We need a reference to the view to set the <see cref="System.Windows.Controls.ChildWindow.DialogResult"/>
        /// in the Ok or Cancel command handlers.
        /// </remarks>
        public void ShowView()
        {
            _view = new EditFeedInfoView(this);

            if (_editInfo != null)
            {
                Url = _editInfo.Url;
                SelectedFeedType = _editInfo.FeedType;
                MaxItemCount = _editInfo.MaxItemCount;
            }

            _view.Show();
        }

        private FeedInfo _editInfo;

        /// <summary>
        /// Gets or sets the <see cref="FeedInfo"/> that is being edited. Can be null.
        /// </summary>
        /// <remarks>
        /// If this property is left null, a new <see cref="FeedInfo"/> instance will be added.
        /// </remarks>
        public FeedInfo EditInfo
        {
            get
            { return _editInfo; }
            set
            {
                _editInfo = value;
                OnPropertyChanged("EditInfo");
            }
        }

        /// <summary>
        /// Gets the collection of <see cref="FeedInfo"/> instances that are being edited.
        /// </summary>
        internal FeedInfoCollection FeedInfos { get; private set; }

        private string _url;

        /// <summary>
        /// Gets or sets the value for the feed Url that is bound to the view.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings",
            Justification = "DataBinding")]
        public string Url
        {
            get { return _url; }
            set
            {
                _url = value;
                OnPropertyChanged("Url");
            }
        }

        private string _selectedFeedType;

        /// <summary>
        /// Gets or sets the value for the feed type that is bound to the view.
        /// </summary>
        public string SelectedFeedType
        {
            get { return _selectedFeedType; }
            set
            {
                _selectedFeedType = value;
                OnPropertyChanged("SelectedFeedType");
            }
        }

        private int _maxItemCount;

        /// <summary>
        /// Gets or sets the value for the maximum number of feed items that is bound to the view.
        /// </summary>
        public int MaxItemCount
        {
            get { return _maxItemCount; }
            set
            {
                _maxItemCount = value;
                OnPropertyChanged("MaxItemCount");
            }
        }

        private FastObservableCollection<string> _feedTypes;

        /// <summary>
        /// Gets the list of all possible feed types that is bound to the view.
        /// </summary>
        public FastObservableCollection<string> FeedTypes
        {
            get
            {
                if (_feedTypes == null)
                {
                    _feedTypes = new FastObservableCollection<string>();
                    _feedTypes.Add(SyndicationVersions.Rss20);
                    _feedTypes.Add(SyndicationVersions.Atom10);

                    if (SelectedFeedType == null)
                    {
                        SelectedFeedType = SyndicationVersions.Rss20;
                    }
                }

                return _feedTypes;
            }
        }

        private DelegateCommand _cancelCommand;

        /// <summary>
        /// Gets the cancel command that is bound to the view.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",
            MessageId = "Seesmic.Sdp.Utils.DelegateCommand.set_Text(System.String)", Justification = "No localization yet.")]
        public DelegateCommand CancelCommand
        {
            get
            {
                if (_cancelCommand == null)
                {
                    _cancelCommand = new DelegateCommand(OnCancelClick);
                    _cancelCommand.Text = "Cancel";
                }

                return _cancelCommand;
            }
        }

        /// <summary>
        /// The handler for the Cancel command.
        /// </summary>
        public void OnCancelClick()
        {
            if (_view != null)
            {
                _view.DialogResult = false;
            }
        }

        private DelegateCommand _okCommand;

        /// <summary>
        /// Gets the Ok command that is bound to the view.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",
            MessageId = "Seesmic.Sdp.Utils.DelegateCommand.set_Text(System.String)", Justification = "No localization yet.")]
        public DelegateCommand OkCommand
        {
            get
            {
                if (_okCommand == null)
                {
                    _okCommand = new DelegateCommand(OnOkClick);
                    _okCommand.Text = "Ok";
                }

                return _okCommand;
            }
        }

        /// <summary>
        /// The handler that is called for the ok command.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
            Justification = "By design.")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",
            MessageId = "System.Windows.MessageBox.Show(System.String,System.String,System.Windows.MessageBoxButton)", Justification = "No localization yet.")]
        public void OnOkClick()
        {
            if (_view != null)
            {
                try
                {
                    if (_editInfo != null)
                    {
                        ViewToData(_editInfo);
                    }
                    else
                    {
                        var feedInfo = new FeedInfo();
                        feedInfo.Enabled = true;
                        ViewToData(feedInfo);

                        FeedInfos.Add(feedInfo);
                    }

                    _view.DialogResult = true;
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString(), "Error", MessageBoxButton.OK);
                }
            }
        }

        /// <summary>
        /// Helper to fill the <paramref name="feedInfo"/> with the values from the view.
        /// </summary>
        /// <param name="feedInfo"></param>
        private void ViewToData(FeedInfo feedInfo)
        {
            feedInfo.FeedType = this.SelectedFeedType;
            feedInfo.Url = this.Url;
            feedInfo.MaxItemCount = this.MaxItemCount;
        }
    }
}